package com.iwhalecloud.uncc.db;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.druid.pool.DruidDataSource;
import com.iwhalecloud.uncc.common.SysConstant;
import com.iwhalecloud.uncc.properties.UnccDsProperties;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.jdbc.core.JdbcTemplate;

@Slf4j
@Configuration
public class DatasourceConfiguration {

    @Bean(value = "dataSource")
    public DynamicDataSource dataSource(UnccDsProperties unccDsProperties) {
        DruidDataSource defaultDataSource = null;
        Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
        List<UnccDsProperties.UnccDsConfig> ucDataSourceList = unccDsProperties.getDatasource();
        for (UnccDsProperties.UnccDsConfig unccDsConfig : ucDataSourceList) {
            DruidDataSource dataSource = new DruidDataSource();
            for (Map.Entry<String, String> entry : unccDsConfig.getProperties().entrySet()) {
                String key = entry.getKey();
                Method[] methods = DruidDataSource.class.getMethods();
                String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
                for (Method m : methods) {
                    if (methodName.equals(m.getName())) {
                        Object value = castStringToX(m.getParameterTypes()[0], entry.getValue());
                        try {
                            m.invoke(dataSource, value);
                        } catch (Exception e) {
                            log.error(ExceptionUtils.getStackTrace(e));
                        }
                        break;
                    }
                }
            }
            targetDataSources.put(unccDsConfig.getCode(), dataSource);
            if(SysConstant.DATASOURCE_DEFAULT.equalsIgnoreCase(unccDsConfig.getCode())){
                defaultDataSource = dataSource;
            }

        }
        if(defaultDataSource == null){
            defaultDataSource = (DruidDataSource) targetDataSources.get("10000");
        }
        DynamicDataSource dynamicDataSource = new DynamicDataSource(defaultDataSource, targetDataSources);
        return dynamicDataSource;
    }

    @Bean(value = "jdbcTemplate")
    @DependsOn(value = { "dataSource" })
    public JdbcTemplate jdbcTemplate(DynamicDataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    private Object castStringToX(Class<?> clazz, String str) {
        Object value = null;
        if ("java.lang.Integer".equals(clazz.getName()) || "int".equals(clazz.getName())) {
            value = Integer.parseInt(str);
        } else if ("java.lang.Boolean".equals(clazz.getName()) || "boolean".equals(clazz.getName())) {
            value = Boolean.parseBoolean(str);
        } else if ("java.lang.Long".equals(clazz.getName()) || "long".equals(clazz.getName())) {
            value = Long.parseLong(str);
        } else {
            value = str;
        }
        return value;
    }
}
